/**
 *
 */
import scala.collection.{ mutable => mutable }
import mutable.Builder
import scala.collection.mutable.ListBuffer
/**
 * @author Gustavo
 *
 */
class SeqIndexadaBidireccional[A](relleno: => A = null, baseRespaldoInicial: Int = -8, topeRespaldoInicial: Int = 8, tamañoMinimoBloqueRelleno: Int = 8) extends scala.collection.IndexedSeq[A] /* with scala.collection.generic.Growable[A] */ {
	private var baseRespaldo = baseRespaldoInicial
	private var topeRespaldo = topeRespaldoInicial
	private var base_itn, tope_itn = 0
	def base = base_itn
	def tope = tope_itn
	def length: Int = tope_itn - base_itn

	private val respaldo: mutable.ArrayBuffer[A] = mutable.ArrayBuffer.fill(topeRespaldo - baseRespaldo)(relleno)
	def apply(idx: Int) = {
		agrandarSiHaceFalta(idx)
		respaldo(idx - baseRespaldo)
	}
	def update(idx: Int, elem: A) {
		agrandarSiHaceFalta(idx)
		respaldo.update(idx - baseRespaldo, elem)
	}

	//	def clear() {
	//		respaldo.clear
	//		base = 0
	//		tope = 0
	//	}
	//	/** Nota: Esta operación fue necesario agregarla cuando se hizo que esta clase implemente [[Growable]] porque ahí esta definido "clear()", el cual es requerido por [[Mundo]]. En la version 2.10 de la libreria podría evitarse ya que existe [[Clearable]] que tiene un metodo abstracto: clear() */
	//	def +=(elem: A): this.type = {
	//		update(tope, elem)
	//		tope += 1
	//		this
	//	}

	private[this] def agrandarSiHaceFalta(idx: Int): Unit = {
		if (idx < base_itn) {
			base_itn = idx
			if (base_itn < baseRespaldo) {
				val tamañoBloqueRelleno = scala.math.max(baseRespaldo - idx, tamañoMinimoBloqueRelleno)
				respaldo.prependAll(mutable.LinearSeq.fill(tamañoBloqueRelleno)(relleno))
				baseRespaldo -= tamañoBloqueRelleno
			}
		} else if (idx >= tope_itn) {
			tope_itn = idx + 1
			if (tope_itn > topeRespaldo) {
				val tamañoBloqueRelleno = scala.math.max(tope_itn - topeRespaldo, tamañoMinimoBloqueRelleno)
				respaldo.appendAll(mutable.LinearSeq.fill(tamañoBloqueRelleno)(relleno))
				topeRespaldo += tamañoBloqueRelleno
			}
		}
	}

	override def iterator: Iterator[A] = new Elements(base_itn, tope_itn)

	def zipWithIndex[A1 >: A]: List[(A,Int)] = {
		val b = ListBuffer[(A,Int)]() 
		var i = base_itn
		for (x <- this) {
			b += ((x, i))
			i += 1
		}
		b.result
	}
}
//}

//object SeqIndexadaBidireccional extends scala.collection.generic.SeqFactory[SeqIndexadaBidireccional] {
//	implicit def canBuildFrom[A]: scala.collection.generic.CanBuildFrom[Coll, A, SeqIndexadaBidireccional[A]] = new GenericCanBuildFrom[A]
//	
//	def newBuilder[A]: Builder[A, SeqIndexadaBidireccional[A]] = new SeqIndexadaBidireccionalBuilder[A]
//
//	class SeqIndexadaBidireccionalBuilder[A] extends Builder[A, SeqIndexadaBidireccional[A]] {
//		val respaldo: mutable.ArrayBuffer[A] = new mutable.ArrayBuffer[A]
//		def +=(elem: A): this.type = {
//			this.respaldo.+=(elem)
//			this
//		}
//		def clear(): Unit = {
//			respaldo.clear
//		}
//
//		def result(): SeqIndexadaBidireccional[A] = {
//			new SeqIndexadaBidireccional[A]()
//		}
//	}
//}